๐ŸŒบ

Entity ๊ธฐ๋ณธ ์†์„ฑ(Annotation)

01. Entity๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์–ด๋…ธํ…Œ์ด์…˜

@Entity ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉ!

โ–ถ๏ธ @Id๋ผ๋Š” ๊ธฐ๋ณธํ‚ค๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์–ด๋…ธํ…Œ์ด์…˜๋„ ๋ฐ˜๋“œ์‹œ ํ•„์š”!

02. @GeneratedValue

/*
 * Copyright (c) 2008, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Linda DeMichiel - 2.1
//     Linda DeMichiel - 2.0

package javax.persistence;

import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static javax.persistence.GenerationType.AUTO;

/**
 * Provides for the specification of generation strategies for the
 * values of primary keys. 
 *
 * <p> The <code>GeneratedValue</code> annotation
 * may be applied to a primary key property or field of an entity or
 * mapped superclass in conjunction with the {@link Id} annotation.
 * The use of the <code>GeneratedValue</code> annotation is only
 * required to be supported for simple primary keys.  Use of the
 * <code>GeneratedValue</code> annotation is not supported for derived
 * primary keys.
 *
 * <pre>
 *
 *     Example 1:
 *
 *     &#064;Id
 *     &#064;GeneratedValue(strategy=SEQUENCE, generator="CUST_SEQ")
 *     &#064;Column(name="CUST_ID")
 *     public Long getId() { return id; }
 *
 *     Example 2:
 *
 *     &#064;Id
 *     &#064;GeneratedValue(strategy=TABLE, generator="CUST_GEN")
 *     &#064;Column(name="CUST_ID")
 *     Long id;
 * </pre>
 *
 * @see Id
 * @see TableGenerator
 * @see SequenceGenerator
 *
 * @since 1.0
 */
@Target({METHOD, FIELD})
@Retention(RUNTIME)

public @interface GeneratedValue {

    /**
     * (Optional) The primary key generation strategy
     * that the persistence provider must use to
     * generate the annotated entity primary key.
     */
    GenerationType strategy() default AUTO;

    /**
     * (Optional) The name of the primary key generator
     * to use as specified in the {@link SequenceGenerator} 
     * or {@link TableGenerator} annotation.
     * <p> Defaults to the id generator supplied by persistence provider.
     */
    String generator() default "";
}
/*
 * Copyright (c) 2008, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Linda DeMichiel - 2.1
//     Linda DeMichiel - 2.0

package javax.persistence;

/** 
 * Defines the types of primary key generation strategies. 
 *
 * @see GeneratedValue
 *
 * @since 1.0
 */
public enum GenerationType { 

    /**
     * Indicates that the persistence provider must assign 
     * primary keys for the entity using an underlying 
     * database table to ensure uniqueness.
     */
    TABLE, 

    /**
     * Indicates that the persistence provider must assign 
     * primary keys for the entity using a database sequence.
     */
    SEQUENCE, 

    /**
     * Indicates that the persistence provider must assign 
     * primary keys for the entity using a database identity column.
     */
    IDENTITY, 

    /**
     * Indicates that the persistence provider should pick an 
     * appropriate strategy for the particular database. The 
     * <code>AUTO</code> generation strategy may expect a database 
     * resource to exist, or it may attempt to create one. A vendor 
     * may provide documentation on how to create such resources 
     * in the event that it does not support schema generation 
     * or cannot create the schema resource at runtime.
     */
    AUTO
}

@GeneratedValue๋ฅผ ์ถ”์ ํ•˜๋‹ค ๋ณด๋ฉด, GenerationType์ด๋ผ๋Š” ์—ด๊ฑฐํ˜•์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ์—ด๊ฑฐํ˜•์€ ํ…Œ์ด๋ธ”/์‹œํ€€์Šค/Identity/Auto ์ด 4 ๊ฐ€์ง€ ํƒ€์ž…์˜ ์ „๋žต์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค

-H2 db์—์„œ๋„ ์ด ์ „๋žต์„ ์ž์ฃผ ์‚ฌ์šฉ

03. @Table

/*
 * Copyright (c) 2008, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Linda DeMichiel - 2.1
//     Linda DeMichiel - 2.0

package javax.persistence;

import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Specifies the primary table for the annotated entity. Additional
 * tables may be specified using {@link SecondaryTable} or {@link
 * SecondaryTables} annotation.
 *
 * <p> If no <code>Table</code> annotation is specified for an entity 
 * class, the default values apply.
 *
 * <pre>
 *    Example:
 *
 *    &#064;Entity
 *    &#064;Table(name="CUST", schema="RECORDS")
 *    public class Customer { ... }
 * </pre>
 *
 * @since 1.0
 */
@Target(TYPE) 
@Retention(RUNTIME)
public @interface Table {

    /**
     * (Optional) The name of the table.
     * <p> Defaults to the entity name.
     */
    String name() default "";

    /** (Optional) The catalog of the table.
     * <p> Defaults to the default catalog.
     */
    String catalog() default "";

    /** (Optional) The schema of the table.
     * <p> Defaults to the default schema for user.
     */
    String schema() default "";

    /**
     * (Optional) Unique constraints that are to be placed on 
     * the table. These are only used if table generation is in 
     * effect. These constraints apply in addition to any constraints 
     * specified by the <code>Column</code> and <code>JoinColumn</code> 
     * annotations and constraints entailed by primary key mappings.
     * <p> Defaults to no additional constraints.
     */
    UniqueConstraint[] uniqueConstraints() default {};

    /**
     * (Optional) Indexes for the table.  These are only used if
     * table generation is in effect.  Note that it is not necessary
     * to specify an index for a primary key, as the primary key
     * index will be created automatically.
     *
     * @since 2.1
     */
    Index[] indexes() default {};
}

์œ„์˜ ํ…Œ์ด๋ธ”์„ ์‚ดํŽด๋ณด๋ฉด, ํ…Œ์ด๋ธ” ์ด๋ฆ„๊ณผ ์นดํƒˆ๋กœ๊ทธ, ์Šคํ‚ค๋งˆ, ์ธ๋ฑ์Šค ๋“ฑ์— ๋Œ€ํ•ด์„œ ์ œ๊ณต์„ ํ•ด์ฃผ๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ๋‹ค

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="created_at")
    private Date createdAt;
    @Column(name="updated_at")
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;
}

๊ทธ๋ฆฌ๊ณ  ์œ„์—์„œ๋Š” @Table(name='user')๋กœ ๋ช…์‹œํ•ด์ฃผ์—ˆ๋Š”๋ฐ, ํ…Œ์ด๋ธ” ์ด๋ฆ„์€ ์ž๋™์œผ๋กœ ํด๋ž˜์Šค๋ช…๊ณผ ๋งค์นญ๋˜๊ธฐ ๋•Œ๋ฌธ์— @Table๋กœ ๋ช…์‹œํ•ด์ฃผ์–ด๋„ ๊ดœ์ฐฎ๋‹ค!

๋‹ค๋งŒ, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด๋‚˜ ์ด๊ด€์ž‘์—…์„ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š”, @Table(name=ํ…Œ์ด๋ธ”๋ช…) ์ฒ˜๋Ÿผ ๊ธฐ์ž…ํ•ด์ฃผ์–ด์•ผ ํ•  ์ƒํ™ฉ๋„ ์กด์žฌํ•œ๋‹ค!

์ด๋ฒˆ์—๋Š” ํ…Œ์ด๋ธ” ์ด๋ฆ„์„ ๋‚˜ํƒ€๋‚ด๋Š” name ์†์„ฑ์˜ ๊ฐ’์„ "user_legacy"๋กœ ๋ณ€๊ฒฝํ•ด๋ณด์ž

๋ฌผ๋ก , data.sql์—์„œ ํ…Œ์ด๋ธ”๋ช…์„ user๋ผ๊ณ  ํ•ด๋‘์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋ถ„๋ช…ํžˆ ์˜ค๋ฅ˜๋Š” ๋‚  ๊ฒƒ์ด๋‹ค

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name="user_legacy")
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="created_at")
    private Date createdAt;
    @Column(name="updated_at")
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;
}
create table user_legacy (
       id bigint not null,
        active boolean,
        created_at timestamp,
        email varchar(255),
        name varchar(255),
        updated_at timestamp,
        primary key (id)
    )

ํ•˜์ง€๋งŒ, ์ฟผ๋ฆฌ์—์„œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•  ๋•Œ user_legacy๋กœ ์‹คํ–‰๋˜์—ˆ์Œ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค

๐ŸŒŸ ํ•˜์ง€๋งŒ, ์ผ๋ฐ˜์ ์œผ๋กœ ํ…Œ์ด๋ธ”๊ณผ ์—”ํ‹ฐํ‹ฐ๋Š” 1:1 ๊ด€๊ณ„๊ฐ€ ๋˜์–ด ์ด๋ฆ„์ด ๋™์ผํ•œ ๊ฒƒ์ด ์ข‹๋‹ค!

03-1. @Table ์–ด๋…ธํ…Œ์ด์…˜์—์„œ ์ธ๋ฑ์Šค์™€ UNIQUE ์ œ์•ฝ์กฐ๊ฑด ๋ถ™์—ฌ์ฃผ๊ธฐ- indexes={@Index(columnList="์ปฌ๋Ÿผ๋ช…")} , uniqueConstraints={@UniqueConstraint(columnNames={"์ปฌ๋Ÿผ๋ช…"})}

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(indexes = {@Index(columnList = "name")},uniqueConstraints = {@UniqueConstraint(columnNames = {"email"})})
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="created_at")
    private Date createdAt;
    @Column(name="updated_at")
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;
}

์œ„์—์„œ ์ž ๊น ์–ธ๊ธ‰ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ Table ์–ด๋…ธํ…Œ์ด์…˜ ๋‚ด์—์„œ๋Š” ์ธ๋ฑ์Šค์™€ UNIQUE ์ œ์•ฝ์กฐ๊ฑด์„ ๊ฑธ์–ด์ค„ ์ˆ˜ ์žˆ๋‹ค!

์ด๋Š” ๊ฐ๊ฐ indexes={@Index(columnList="์ปฌ๋Ÿผ๋ช…")} , uniqueConstraints={@UniqueConstraint(columnNames={"์ปฌ๋Ÿผ๋ช…"})} ์„ ์ด์šฉํ•ด์„œ ์œ„์™€ ๊ฐ™์ด ์ ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค!

Hibernate: 
    
    drop table if exists address CASCADE 
Hibernate: 
    
    drop table if exists user CASCADE 
Hibernate: 
    
    drop sequence if exists hibernate_sequence
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: 
    
    create table address (
       id bigint not null,
        primary key (id)
    )
Hibernate: 
    
    create table user (
       id bigint not null,
        active boolean,
        created_at timestamp,
        email varchar(255),
        name varchar(255),
        updated_at timestamp,
        primary key (id)
    )
Hibernate: create index IDXgj2fy3dcix7ph7k8684gka40c on user (name)
Hibernate: 
    
    alter table user 
       add constraint UKob8kqyqqgmefl0aco34akdtpe unique (email)

๊ทธ๋ฆฌ๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด DDL์—์„œ `ํ…Œ์ด๋ธ”์ด๋‚˜ ์‹œํ€€์Šค๊ฐ€ ์กด์žฌํ•˜๋ฉด ์‚ญ์ œํ•˜๋Š” ๊ฒƒ์„ ๋จผ์ € ์ˆ˜ํ–‰ํ•˜๊ณ  ํ…Œ์ด๋ธ”์„ ๋งŒ๋“œ๋Š” ํ˜•ํƒœ๋ฅผ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๊ณ 

์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“ค๊ณ , UNIQUE ์ œ์•ฝ์กฐ๊ฑด์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ๋‹ค!

ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ์ธ๋ฑ์Šค๋‚˜ ์ œ์•ฝ์กฐ๊ฑด์— ๋Œ€ํ•œ ์ ์šฉ์‚ฌํ•ญ์€ ์‹ค์ œ DB์— ์ €์žฅ๋˜๋Š” ๊ฒƒ๊ณผ๋Š” ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค! ์ผ๋ฐ˜์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” select, update, insert, delete ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ์—๋Š” ์–ด๋–ค ํšจ๋ ฅ๋„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค!

๋”ฐ๋ผ์„œ ์ธ๋ฑ์Šค๋‚˜ ์ œ์•ฝ์กฐ๊ฑด์€ DB์— ๋งก๊ธฐ๊ณ  ์—”ํ‹ฐํ‹ฐ์— ํ‘œ๊ธฐํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ณด๋‹ค ๋งŽ๋‹ค!

04. @Column

๊ฐ์ฒด ํ•„๋“œ์— ๊ฐ ์ปฌ๋Ÿผ ์†์„ฑ์„ ์ง€์ •

์˜ˆ์ „์—๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด์„œ createdAt๊ณผ ๊ฐ™์€ ํ•„๋“œ๋ฅผ ๋ชจ์Œ์„ ์ตœ๋Œ€ํ•œ ์ ๊ฒŒ ์“ฐ๊ธฐ ์œ„ํ•ด์„œ crtdat์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ–ˆ์—ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Š” ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ด ๊ฒฝ์šฐ์— Column์„ ์ ์šฉํ•˜๋ฉด ์ข‹๋‹ค![A]

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(indexes = {@Index(columnList = "name")},uniqueConstraints = {@UniqueConstraint(columnNames = {"email"})})
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="created_at")
    private Date createdAt;
    @Column(name="updated_at")
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;
}

๐Ÿ‘‰[A] ๊ณผ๊ฑฐ์— ์‚ฌ์šฉํ•˜๋˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ•„๋“œ๋ช…์— ์ž๋ฐ” ํ•„๋“œ๋ฅผ ๋งค์นญ์‹œ์ผœ์ค„ ๋•Œ, ๊ฐ€๋…์„ฑ์„ UP!

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(indexes = {@Index(columnList = "name")},uniqueConstraints = {@UniqueConstraint(columnNames = {"email"})})
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="crtdat")
    private Date createdAt;
    @Column(name="updated_at")
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;
}

๊ทธ๋Ÿฌ๋ฉด ์ง€๊ธˆ์€ ๋‹น์—ฐํžˆ ์˜ค๋ฅ˜๊ฐ€ ๋‚  ์ˆ˜๋ฐ–์— ์—†์ง€๋งŒ(data.sql์— insertํ•  ์ปฌ๋Ÿผ๋ช…์„ createdAt์œผ๋กœ ์ ์–ด๋‘์—ˆ๊ธฐ ๋•Œ๋ฌธ), DDL๋งŒ ํ™•์ธํ•ด๋ณธ๋‹ค๋ฉด, crtdat์ปฌ๋Ÿผ์ด ์ƒ๊ธด ๊ฒƒ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค

Hibernate: 
    
    create table user (
       id bigint not null,
        active boolean,
        crtdat timestamp,
        email varchar(255),
        name varchar(255),
        updated_at timestamp,
        primary key (id)
    )

04-1. @Column-nullable์†์„ฑ

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(indexes = {@Index(columnList = "name")},uniqueConstraints = {@UniqueConstraint(columnNames = {"email"})})
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="crtdat")
    private Date createdAt;
    @Column(name="updated_at",nullable = false)
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;
}
Hibernate: 
    
    create table user (
       id bigint not null,
        active boolean,
        crtdat timestamp,
        email varchar(255),
        name varchar(255),
        updated_at timestamp not null,
        primary key (id)
    )

๊ทธ๋Ÿฌ๋ฉด, nullable=false๋ฅผ ์ง€์ •ํ•ด์ค€ ํ•„๋“œ์— not null์ด ๋ถ™์€ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค


/*
 * Copyright (c) 2008, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Linda DeMichiel - 2.1
//     Linda DeMichiel - 2.0


package javax.persistence;

import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Specifies the mapped column for a persistent property or field.
 * If no <code>Column</code> annotation is specified, the default values apply.
 *
 * <blockquote><pre>
 *    Example 1:
 *
 *    &#064;Column(name="DESC", nullable=false, length=512)
 *    public String getDescription() { return description; }
 *
 *    Example 2:
 *
 *    &#064;Column(name="DESC",
 *            columnDefinition="CLOB NOT NULL",
 *            table="EMP_DETAIL")
 *    &#064;Lob
 *    public String getDescription() { return description; }
 *
 *    Example 3:
 *
 *    &#064;Column(name="ORDER_COST", updatable=false, precision=12, scale=2)
 *    public BigDecimal getCost() { return cost; }
 *
 * </pre></blockquote>
 *
 *
 * @since 1.0
 */ 
@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public @interface Column {

    /**
     * (Optional) The name of the column. Defaults to 
     * the property or field name.
     */
    String name() default "";

    /**
     * (Optional) Whether the column is a unique key.  This is a 
     * shortcut for the <code>UniqueConstraint</code> annotation at the table 
     * level and is useful for when the unique key constraint 
     * corresponds to only a single column. This constraint applies 
     * in addition to any constraint entailed by primary key mapping and 
     * to constraints specified at the table level.
     */
    boolean unique() default false;

    /**
     * (Optional) Whether the database column is nullable.
     */
    boolean nullable() default true;

    /**
     * (Optional) Whether the column is included in SQL INSERT 
     * statements generated by the persistence provider.
     */
    boolean insertable() default true;

    /**
     * (Optional) Whether the column is included in SQL UPDATE 
     * statements generated by the persistence provider.
     */
    boolean updatable() default true;

    /**
     * (Optional) The SQL fragment that is used when 
     * generating the DDL for the column.
     * <p> Defaults to the generated SQL to create a
     * column of the inferred type.
     */
    String columnDefinition() default "";

    /**
     * (Optional) The name of the table that contains the column. 
     * If absent the column is assumed to be in the primary table.
     */
    String table() default "";

    /**
     * (Optional) The column length. (Applies only if a
     * string-valued column is used.)
     */
    int length() default 255;

    /**
     * (Optional) The precision for a decimal (exact numeric) 
     * column. (Applies only if a decimal column is used.)
     * Value must be set by developer if used when generating 
     * the DDL for the column.
     */
    int precision() default 0;

    /**
     * (Optional) The scale for a decimal (exact numeric) column. 
     * (Applies only if a decimal column is used.)
     */
    int scale() default 0;
}

์œ„๋Š” Column ์–ด๋…ธํ…Œ์ด์…˜์— ๋Œ€ํ•œ ๋ถ€๋ถ„์ธ๋ฐ,

-Table์—์„œ๋Š” ๋ณตํ•ฉ ์ปฌ๋Ÿผ์— ๋Œ€ํ•ด unique ์ œ์•ฝ์กฐ๊ฑด์„ ๊ฑธ ์ˆ˜ ์žˆ๋Š” uniqueConstraints๊ฐ€ ์žˆ๋‹ค๋ฉด,

column์—๋Š” ๋‹จ๋…์ ์œผ๋กœ ๊ฐ ํ•„๋“œ์— ๊ฑธ ์ˆ˜ ์žˆ๋„๋ก ๋˜์–ด์žˆ๋‹ค!

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(indexes = {@Index(columnList = "name")},uniqueConstraints = {@UniqueConstraint(columnNames = {"email"})})
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name",unique = true)
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="crtdat")
    private Date createdAt;
    @Column(name="updated_at",nullable = false)
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;
}
create table user (
       id bigint not null,
        active boolean,
        crtdat timestamp,
        email varchar(255),
        name varchar(255),
        updated_at timestamp not null,
        primary key (id)
    )
Hibernate: create index IDXgj2fy3dcix7ph7k8684gka40c on user (name)
Hibernate: 
    
    alter table user 
       add constraint UKob8kqyqqgmefl0aco34akdtpe unique (email)
Hibernate: 
    
    alter table user 
       add constraint UK_gj2fy3dcix7ph7k8684gka40c unique (name)

์ด๋ฉ”์ผ ํ•„๋“œ์˜ ๊ธธ์ด๋ฅผ 4000์œผ๋กœ ๋Š˜๋ ค๋ณด์ž

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(indexes = {@Index(columnList = "name")},uniqueConstraints = {@UniqueConstraint(columnNames = {"email"})})
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name",unique = true)
    private String name;
    @NonNull
    @Column(name="email",length = 4000)
    private String email;
    @Column(name="crtdat")
    private Date createdAt;
    @Column(name="updated_at",nullable = false)
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;
}
create table user (
       id bigint not null,
        active boolean,
        crtdat timestamp,
        email varchar(4000),
        name varchar(255),
        updated_at timestamp not null,
        primary key (id)
    )

๊ทธ๋Ÿฌ๋ฉด ์ด์ œ ์ด๋ฉ”์ผ ํ•„๋“œ์˜ ๊ธธ์ด๋Š” ๋”์ด์ƒ 255๊ฐ€ ์•„๋‹ˆ๋ผ 4000์ด ๋˜์—ˆ์Œ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค

๋จผ์ € User ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ ์ •๋ฆฌํ•ด๋ณด๊ณ , ์•„๋ž˜์™€ ๊ฐ™์ด ํ…Œ์ŠคํŠธํ•ด๋ณด์ž

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(indexes = {@Index(columnList = "name")},uniqueConstraints = {@UniqueConstraint(columnNames = {"email"})})
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email",length = 4000)
    private String email;
    @Column(name="created_at")
    private Date createdAt;
    @Column(name="updated_at")
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;
}
@Test
    public void dmlAccess(){
        User user=new User();

        user.setName("martin");
        user.setEmail("martin2@fastcampus.com");

        userRepository.save(user);//insert

        User user2=userRepository.findById(1L).orElseThrow(RuntimeException::new);
        user2.setEmail("update_1l_id@fastcampus.com");

        userRepository.save(user2);//update
    }

๊ทธ๋Ÿฌ๋ฉด ๋‹น์—ฐํžˆ, ์ฒ˜์Œ์—๋Š” insertable๊ณผ updatable์˜ ๊ธฐ๋ณธ๊ฐ’์ด true๋กœ ๋˜์–ด์žˆ์–ด์„œ insert, update๊ฐ€ ๊ฐ€๋Šฅํ•˜์—ฌ ์•„๋ž˜์™€ ๊ฐ™์€ ์ฟผ๋ฆฌ๋ฅผ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค

Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        user
        (active, created_at, email, name, updated_at, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.name as name5_1_0_,
        user0_.updated_at as updated_6_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.name as name5_1_0_,
        user0_.updated_at as updated_6_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        user 
    set
        active=?,
        created_at=?,
        email=?,
        name=?,
        updated_at=? 
    where
        id=?

๐ŸŒŸ ์ด๋ฒˆ์—๋Š” created_at ํ•„๋“œ์— ๋Œ€ํ•ด์„œ update๋˜์ง€ ๋ชปํ•˜๋„๋ก updatable=false๋ฅผ ์„ค์ •ํ•ด์ฃผ๊ณ , updated_at ํ•„๋“œ์— ๋Œ€ํ•ด์„œ insert๋˜์ง€ ๋ชปํ•˜๋„๋ก insertable=false๋ฅผ ์„ค์ •ํ•ด์ฃผ์ž

package com.example.jpa_sort_practice.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="created_at",updatable = false)
    private Date createdAt;
    @Column(name="updated_at",insertable = false)
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;
}

๊ทธ๋ฆฌ๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ ˆ์ฝ”๋“œ๋“ค์˜ ๋ฌถ์Œ์œผ๋กœ ๋ณด๊ธฐ ์œ„ํ•ด์„œ ์ถœ๋ ฅ์„ ํ•ด์ฃผ๋ฉด

@Test
    public void dmlAccess(){
        User user=new User();

        user.setName("martin");
        user.setEmail("martin2@fastcampus.com");

        userRepository.save(user);//insert

        User user2=userRepository.findById(1L).orElseThrow(RuntimeException::new);
        user2.setEmail("update_1l_id@fastcampus.com");

        userRepository.save(user2);//update

        userRepository.findAll().forEach(System.out::println);
    }
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        user
        (active, created_at, email, name, id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.name as name5_1_0_,
        user0_.updated_at as updated_6_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.name as name5_1_0_,
        user0_.updated_at as updated_6_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        user 
    set
        active=?,
        email=?,
        name=?,
        updated_at=? 
    where
        id=?
Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.active as active2_1_,
        user0_.created_at as created_3_1_,
        user0_.email as email4_1_,
        user0_.name as name5_1_,
        user0_.updated_at as updated_6_1_ 
    from
        user user0_
User(id=1, name=martin, email=update_1l_id@fastcampus.com, createdAt=2021-08-19 14:32:55.101, updatedAt=2021-08-19 14:32:55.101, active=true)
User(id=2, name=dennis, email=dennis@fastcampus.com, createdAt=2021-08-19 14:32:55.114, updatedAt=2021-08-19 14:32:55.114, active=true)
User(id=3, name=sophia, email=sophia@slowcampus.com, createdAt=2021-08-19 14:32:55.114, updatedAt=2021-08-19 14:32:55.114, active=false)
User(id=4, name=james, email=james@slowcampus.com, createdAt=2021-08-19 14:32:55.114, updatedAt=2021-08-19 14:32:55.114, active=false)
User(id=5, name=martin, email=martin@another.com, createdAt=2021-08-19 14:32:55.115, updatedAt=2021-08-19 14:32:55.115, active=true)
User(id=6, name=martin, email=martin2@fastcampus.com, createdAt=null, updatedAt=null, active=false)

id=6, ์ฆ‰ ์ƒˆ๋กœ ์‚ฝ์ž…ํ•œ martin์€ updated_at ์ด insertable=false์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ’์—์„œ๋„, ์ฟผ๋ฆฌ์—์„œ๋„ ๋น ์ง„ ๊ฒƒ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๊ณ 

id=1์ธ martin์€ created_at์ด updatable=false๋ผ์„œ ์ฟผ๋ฆฌ์—์„œ update ์‹œ created_at์ด ๋น ์ง„ ๊ฒƒ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค!

๐ŸŒŸ ์—”ํ‹ฐํ‹ฐ๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๊ฐ์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์— DB ๋ ˆ์ฝ”๋“œ์˜ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜์˜ํ•œ๋‹ค! ํ•˜์ง€๋งŒ, ๊ฐ์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ณ„๋„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ–๊ณ  ์‹ถ์€ ๋‹ˆ์ฆˆ๋„ ์ƒ๊ธฐ๊ธฐ ๋งˆ๋ จ์ธ๋ฐ, ์ด๋ฅผ ์œ„ํ•ด ์กด์žฌํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ฐ”๋กœ @Transient ์ด๋‹ค!

05. @Transient

์ถ”๊ฐ€์ ์œผ๋กœ, testData๋ผ๋Š” ํ•„๋“œ๋ฅผ User ๊ฐ์ฒด์— ์ถ”๊ฐ€ํ•ด๋ณด์ž

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="created_at",updatable = false)
    private Date createdAt;
    @Column(name="updated_at",insertable = false)
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;

    private String testData;
}

Hibernate: 
    
    create table user (
       id bigint not null,
        active boolean,
        created_at timestamp,
        email varchar(255),
        name varchar(255),
        test_data varchar(255),
        updated_at timestamp,
        primary key (id)
    )
(์ค‘๋žต)
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        user
        (active, created_at, email, name, test_data, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.name as name5_1_0_,
        user0_.test_data as test_dat6_1_0_,
        user0_.updated_at as updated_7_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.name as name5_1_0_,
        user0_.test_data as test_dat6_1_0_,
        user0_.updated_at as updated_7_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        user 
    set
        active=?,
        email=?,
        name=?,
        test_data=?,
        updated_at=? 
    where
        id=?
Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.active as active2_1_,
        user0_.created_at as created_3_1_,
        user0_.email as email4_1_,
        user0_.name as name5_1_,
        user0_.test_data as test_dat6_1_,
        user0_.updated_at as updated_7_1_ 
    from
        user user0_
User(id=1, name=martin, email=update_1l_id@fastcampus.com, createdAt=2021-08-19 14:43:22.501, updatedAt=2021-08-19 14:43:22.501, active=true, testData=null)
User(id=2, name=dennis, email=dennis@fastcampus.com, createdAt=2021-08-19 14:43:22.517, updatedAt=2021-08-19 14:43:22.517, active=true, testData=null)
User(id=3, name=sophia, email=sophia@slowcampus.com, createdAt=2021-08-19 14:43:22.518, updatedAt=2021-08-19 14:43:22.518, active=false, testData=null)
User(id=4, name=james, email=james@slowcampus.com, createdAt=2021-08-19 14:43:22.518, updatedAt=2021-08-19 14:43:22.518, active=false, testData=null)
User(id=5, name=martin, email=martin@another.com, createdAt=2021-08-19 14:43:22.519, updatedAt=2021-08-19 14:43:22.519, active=true, testData=null)
User(id=6, name=martin, email=martin2@fastcampus.com, createdAt=null, updatedAt=null, active=false, testData=null)

๊ทธ๋Ÿฌ๋ฉด, test_data๋ผ๋Š” ํ•„๋“œ๊ฐ€ ์ƒ๊ฒจ๋‚˜๊ณ , insert์™€ update ์‹œ ํ•ด๋‹น ํ•„๋“œ๊ฐ€ ๋…ธ์ถœ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค

ํ•˜์ง€๋งŒ ์ด testData๋Š” DB์—๋Š” ๋ฐ˜์˜ํ•˜์ง€ ์•Š๊ณ  ๊ฐ์ฒด์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€ ์˜ค๋ธŒ์ ํŠธ์˜ ์†์„ฑ์ผ ์ˆ˜๋„ ์žˆ๋‹ค

๐Ÿ“Œ์ด๋•Œ @Transient๋ฅผ ๋ถ™์—ฌ์ฃผ๋ฉด, ์ด ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํ•„๋“œ๋Š” DB์— ๋ฐ˜์˜๋˜์ง€ ์•Š์Œ์„ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="created_at",updatable = false)
    private Date createdAt;
    @Column(name="updated_at",insertable = false)
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;

    @Transient
    private String testData;
}
create table user (
       id bigint not null,
        active boolean,
        created_at timestamp,
        email varchar(255),
        name varchar(255),
        updated_at timestamp,
        primary key (id)
    )
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        user
        (active, created_at, email, name, id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.name as name5_1_0_,
        user0_.updated_at as updated_6_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.name as name5_1_0_,
        user0_.updated_at as updated_6_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        user 
    set
        active=?,
        email=?,
        name=?,
        updated_at=? 
    where
        id=?
Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.active as active2_1_,
        user0_.created_at as created_3_1_,
        user0_.email as email4_1_,
        user0_.name as name5_1_,
        user0_.updated_at as updated_6_1_ 
    from
        user user0_

๊ทธ๋Ÿฌ๋ฉด ์•ž์„œ ํ™•์ธ๋˜์—ˆ๋˜ testData๊ฐ€ DB ํ•„๋“œ์—๋Š” ์ „ํ˜€ ๋ฐ˜์˜์ด ๋˜์ง€ ์•Š๋Š” ๊ฒƒ(DDL, DML์— ๋ชจ๋‘ ๋ฐ˜์˜xโ–ถ๏ธ ์˜์†์„ฑx)์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฌ๋ฉด์„œ ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์™€ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ™์ดํ•˜๊ฒŒ ๋œ๋‹ค

๐ŸŒŸ 06. Enum์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ

๋จผ์ € ์•„๋ž˜์™€ ๊ฐ™์ด ์„ฑ๋ณ„์— ๋Œ€ํ•œ enum์„ ๋งŒ๋“ค์–ด๋ณด์ž

package com.example.jpa_entity.domain;

public enum Gender {
    MALE,
    FEMALE
}

๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฌํ•œ enum์„ User์˜ ํ•„๋“œ๋กœ์จ ๋„ฃ์–ด์ฃผ๋„๋ก ํ•˜์ž

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="created_at",updatable = false)
    private Date createdAt;
    @Column(name="updated_at",insertable = false)
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;

    @Transient
    private String testData;

    //enum
    private Gender gender;
}

๊ทธ๋ฆฌ๊ณ  ์•„์ด๋””๊ฐ€ 1์ธ user๋ฅผ ์ฐพ์•„์„œ ์„ฑ๋ณ„์„ MALE๋กœ ์„ค์ •ํ•˜๋Š” update๋ฅผ ์‹คํ–‰ํ•ด์ฃผ์ž

@Test
    public void enumTest(){
        User user=userRepository.findById(1L).orElseThrow(RuntimeException::new);

        user.setGender(Gender.MALE);
        userRepository.save(user);//update

        userRepository.findAll().forEach(System.out::println);

    }

๊ทธ๋Ÿฌ๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ์•„์ด๋””๊ฐ€ 1์ธ ์‚ฌ์šฉ์ž๋งŒ gender๊ฐ’์œผ๋กœ MALE์ด ๋“ค์–ด๊ฐ„ ๊ฒƒ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค

Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.gender as gender5_1_0_,
        user0_.name as name6_1_0_,
        user0_.updated_at as updated_7_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.gender as gender5_1_0_,
        user0_.name as name6_1_0_,
        user0_.updated_at as updated_7_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        user 
    set
        active=?,
        email=?,
        gender=?,
        name=?,
        updated_at=? 
    where
        id=?
Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.active as active2_1_,
        user0_.created_at as created_3_1_,
        user0_.email as email4_1_,
        user0_.gender as gender5_1_,
        user0_.name as name6_1_,
        user0_.updated_at as updated_7_1_ 
    from
        user user0_
User(id=1, name=martin, email=martin@fastcampus.com, createdAt=2021-08-20 14:04:02.216, updatedAt=2021-08-20 14:04:02.216, active=true, testData=null, gender=MALE)
User(id=2, name=dennis, email=dennis@fastcampus.com, createdAt=2021-08-20 14:04:02.232, updatedAt=2021-08-20 14:04:02.232, active=true, testData=null, gender=null)
User(id=3, name=sophia, email=sophia@slowcampus.com, createdAt=2021-08-20 14:04:02.232, updatedAt=2021-08-20 14:04:02.232, active=false, testData=null, gender=null)
User(id=4, name=james, email=james@slowcampus.com, createdAt=2021-08-20 14:04:02.233, updatedAt=2021-08-20 14:04:02.233, active=false, testData=null, gender=null)
User(id=5, name=martin, email=martin@another.com, createdAt=2021-08-20 14:04:02.233, updatedAt=2021-08-20 14:04:02.233, active=true, testData=null, gender=null)

enum์„ ์‚ฌ์šฉํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์„ ๋ณด๋‹ค ์ดํ•ดํ•˜๊ธฐ ์œ„ํ—ค์„œ ์•„์ง ๋ฐฐ์šฐ์ง€๋Š” ์•Š์•˜์ง€๋งŒ ๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ๋ฅผ ์ด์šฉํ•ด๋ณด์ž

package com.example.jpa_entity.repository;

import com.example.jpa_entity.domain.User;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;
import java.util.Map;

public interface UserRepository extends JpaRepository<User,Long> {

    List<User> findTop1ByName(String name);
    List<User> findTop1ByNameOrderByIdDesc(String name);

    List<User> findFirstByNameOrderByIdDescEmailAsc(String name);
    List<User> findFirstByName(String name, Sort sort);

    @Query(value="select * from user limit 1;", nativeQuery = true)
    Map<String, Object> findRawRecord();
}

๊ทธ๋ฆฌ๊ณ  ๊ฐ„๋‹จํ•˜๊ฒŒ ํ…Œ์ŠคํŠธํ•ด๋ณด์ž

@Test
    public void enumTest(){
        User user=userRepository.findById(1L).orElseThrow(RuntimeException::new);

        user.setGender(Gender.MALE);
        userRepository.save(user);//update

        userRepository.findAll().forEach(System.out::println);

        System.out.println(userRepository.findRawRecord().get("gender"));
    }
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.gender as gender5_1_0_,
        user0_.name as name6_1_0_,
        user0_.updated_at as updated_7_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.gender as gender5_1_0_,
        user0_.name as name6_1_0_,
        user0_.updated_at as updated_7_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        user 
    set
        active=?,
        email=?,
        gender=?,
        name=?,
        updated_at=? 
    where
        id=?
Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.active as active2_1_,
        user0_.created_at as created_3_1_,
        user0_.email as email4_1_,
        user0_.gender as gender5_1_,
        user0_.name as name6_1_,
        user0_.updated_at as updated_7_1_ 
    from
        user user0_
User(id=1, name=martin, email=martin@fastcampus.com, createdAt=2021-08-20 14:09:55.478, updatedAt=2021-08-20 14:09:55.478, active=true, testData=null, gender=MALE)
User(id=2, name=dennis, email=dennis@fastcampus.com, createdAt=2021-08-20 14:09:55.494, updatedAt=2021-08-20 14:09:55.494, active=true, testData=null, gender=null)
User(id=3, name=sophia, email=sophia@slowcampus.com, createdAt=2021-08-20 14:09:55.494, updatedAt=2021-08-20 14:09:55.494, active=false, testData=null, gender=null)
User(id=4, name=james, email=james@slowcampus.com, createdAt=2021-08-20 14:09:55.495, updatedAt=2021-08-20 14:09:55.495, active=false, testData=null, gender=null)
User(id=5, name=martin, email=martin@another.com, createdAt=2021-08-20 14:09:55.495, updatedAt=2021-08-20 14:09:55.495, active=true, testData=null, gender=null)
Hibernate: 
    select
        * 
    from
        user limit 1;
0

๊ทธ๋Ÿฌ๋ฉด @Query ์•ˆ์˜ ๋‚ด์šฉ์œผ๋กœ ๋ณด์•„ USER ํ…Œ์ด๋ธ”์—์„œ 1๊ฐœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋‚ด์šฉ์œผ๋กœ ์ถ”์ธก๋œ๋‹ค

๊ทธ๋ฆฌ๊ณ  get("gender")๋ฅผ ํ–ˆ์„ ๋•Œ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”๋ผ๋ณด๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ์œ„์˜ ํ…Œ์ŠคํŠธ์ด๋‹ค

ํ•˜์ง€๋งŒ 0์ด ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค!

ํ•˜์ง€๋งŒ enum์˜ ๋‚ด์šฉ์„ ์•„๋ž˜์ฒ˜๋Ÿผ ๋ณ€๊ฒฝํ•˜๋ฉด 1์ด ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

package com.example.jpa_entity.domain;

public enum Gender {
    FEMALE,
    MALE
}
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.gender as gender5_1_0_,
        user0_.name as name6_1_0_,
        user0_.updated_at as updated_7_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.gender as gender5_1_0_,
        user0_.name as name6_1_0_,
        user0_.updated_at as updated_7_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        user 
    set
        active=?,
        email=?,
        gender=?,
        name=?,
        updated_at=? 
    where
        id=?
Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.active as active2_1_,
        user0_.created_at as created_3_1_,
        user0_.email as email4_1_,
        user0_.gender as gender5_1_,
        user0_.name as name6_1_,
        user0_.updated_at as updated_7_1_ 
    from
        user user0_
User(id=1, name=martin, email=martin@fastcampus.com, createdAt=2021-08-20 14:15:04.59, updatedAt=2021-08-20 14:15:04.59, active=true, testData=null, gender=MALE)
User(id=2, name=dennis, email=dennis@fastcampus.com, createdAt=2021-08-20 14:15:04.602, updatedAt=2021-08-20 14:15:04.602, active=true, testData=null, gender=null)
User(id=3, name=sophia, email=sophia@slowcampus.com, createdAt=2021-08-20 14:15:04.603, updatedAt=2021-08-20 14:15:04.603, active=false, testData=null, gender=null)
User(id=4, name=james, email=james@slowcampus.com, createdAt=2021-08-20 14:15:04.603, updatedAt=2021-08-20 14:15:04.603, active=false, testData=null, gender=null)
User(id=5, name=martin, email=martin@another.com, createdAt=2021-08-20 14:15:04.604, updatedAt=2021-08-20 14:15:04.604, active=true, testData=null, gender=null)
Hibernate: 
    select
        * 
    from
        user limit 1;
1

User์˜ Gender ํ•„๋“œ์— @Enumerated๋ฅผ ๋ถ™์—ฌ๋ณด์ž

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="created_at",updatable = false)
    private Date createdAt;
    @Column(name="updated_at",insertable = false)
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;

    @Transient
    private String testData;

    //enum
    @Enumerated
    private Gender gender;
}

๊ทธ๋ฆฌ๊ณ  Enumerated๋ฅผ ์ž˜ ๋ณด๋ฉด Enum์˜ ํƒ€์ž…์— ๋Œ€ํ•œ ๊ธฐ๋ณธ๊ฐ’์ด ORDINAL ์ฆ‰ ์„œ์ˆ˜๋กœ ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค

(์ด์™ธ์—๋„ String์ด ๊ฐ€๋Šฅ)

๐ŸŒŸ ์ฆ‰, ์ฒซ๋ฒˆ์งธ์— ์œ„์น˜ํ•œ ๊ฐ’์ด 0์ด๊ณ , ๊ทธ ๋‹ค์Œ์ด 1 ์ด๋Ÿฐ ์ˆœ์„œ๋กœ ๋งค๊ฒจ์ ธ์„œ DB์— ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋Ÿฐ๊ฒƒ์ด์—ˆ๋‹ค! ์ด๋Š” ํ…Œ์ŠคํŠธ๋กœ๋Š” ํ™•์ธํ•˜๊ธฐ ์–ด๋ ต๋‹ค(MALE, FEMALE๋กœ ์ถœ๋ ฅ๋˜๊ธฐ ๋•Œ๋ฌธ)

ํ•˜์ง€๋งŒ ์ง€๊ธˆ ํ…Œ์ŠคํŠธํ•ด๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ ์ €์žฅ ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ๊ฑฐ๋‚˜, ํ˜น์€ ์ด์™ธ์˜ ์ƒํ™ฉ์œผ๋กœ ๊ฐ’์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์ž ์žฌ์ ์ธ ๋ฒ„๊ทธ๊ฐ€ ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ORDINAL๋กœ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ ๋ฐ”๋žŒ์งํ•˜์ง€ ๋ชปํ•˜๋‹ค

๐ŸŒŸ ๋”ฐ๋ผ์„œ ๋ฐ˜๋“œ์‹œ Enum์„ ํ•„๋“œ๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด @Enumerated(value=EnumType.String)์„ ์„ค์ •ํ•˜๊ณ  ์‚ฌ์šฉํ•ด์ฃผ์ž!!

package com.example.jpa_entity.domain;

import lombok.*;

import javax.persistence.*;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue
    @Column(name="id")
    private Long id;
    @NonNull
    @Column(name="name")
    private String name;
    @NonNull
    @Column(name="email")
    private String email;
    @Column(name="created_at",updatable = false)
    private Date createdAt;
    @Column(name="updated_at",insertable = false)
    private Date updatedAt;

    //IsNotEmpty ํ™•์ธ์šฉ
    //@OneToMany(fetch=FetchType.EAGER)
    //private List<Address> addresses;

    @Column(name="active")
    private boolean active;

    @Transient
    private String testData;

    //enum
    @Enumerated(EnumType.STRING)
    private Gender gender;
}
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.gender as gender5_1_0_,
        user0_.name as name6_1_0_,
        user0_.updated_at as updated_7_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.active as active2_1_0_,
        user0_.created_at as created_3_1_0_,
        user0_.email as email4_1_0_,
        user0_.gender as gender5_1_0_,
        user0_.name as name6_1_0_,
        user0_.updated_at as updated_7_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        user 
    set
        active=?,
        email=?,
        gender=?,
        name=?,
        updated_at=? 
    where
        id=?
Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.active as active2_1_,
        user0_.created_at as created_3_1_,
        user0_.email as email4_1_,
        user0_.gender as gender5_1_,
        user0_.name as name6_1_,
        user0_.updated_at as updated_7_1_ 
    from
        user user0_
User(id=1, name=martin, email=martin@fastcampus.com, createdAt=2021-08-20 14:21:14.97, updatedAt=2021-08-20 14:21:14.97, active=true, testData=null, gender=MALE)
User(id=2, name=dennis, email=dennis@fastcampus.com, createdAt=2021-08-20 14:21:14.981, updatedAt=2021-08-20 14:21:14.981, active=true, testData=null, gender=null)
User(id=3, name=sophia, email=sophia@slowcampus.com, createdAt=2021-08-20 14:21:14.982, updatedAt=2021-08-20 14:21:14.982, active=false, testData=null, gender=null)
User(id=4, name=james, email=james@slowcampus.com, createdAt=2021-08-20 14:21:14.983, updatedAt=2021-08-20 14:21:14.983, active=false, testData=null, gender=null)
User(id=5, name=martin, email=martin@another.com, createdAt=2021-08-20 14:21:14.983, updatedAt=2021-08-20 14:21:14.983, active=true, testData=null, gender=null)
Hibernate: 
    select
        * 
    from
        user limit 1;
๐Ÿ“ŒMALE๐Ÿ“Œ

๊ทธ๋Ÿฌ๋ฉด ๋”์ด์ƒ 0์ด๋‚˜ 1๋กœ ์ €์žฅ ์ˆœ์„œ์— ๋”ฐ๋ผ ๋ฐ”๋€Œ์ง€ ์•Š๊ณ , MALE๋กœ DB์— ์ €์žฅ๋˜์—ˆ์Œ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค!

๐ŸŒŸ ์ถ”ํ›„ DB ์žฅ์• ๋‚˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ Enum ์‚ฌ์šฉ์— ์ฃผ์˜ํ•˜์ž!